package org.pupil.invoke.jdk;

import org.pupil.common.Cache;
import org.pupil.invoke.Invocation;
import org.pupil.invoke.Invoker;
import org.pupil.invoke.MethodInvocation;
import org.pupil.utils.ServiceNameBuilder;

import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.util.HashMap;
import java.util.Map;

/**
 * @Description: jdk反射调用方式，将方法在服务提供方本地通过反射代理调用
 * @Author: pupil
 * @Date: 2024/07/09 下午 6:21
 */
public class JdkReflectionInvoker implements Invoker {

    // 根据方法的hashCode，绑定方法代理调用方法
    private Map<Integer, MethodInvocation> methodMap = new HashMap<>();

    @Override
    public Object invoke(Invocation invocation) throws InvocationTargetException, IllegalAccessException, ClassNotFoundException, NoSuchMethodException, InstantiationException {
        // 获取方法的hashCode
        final Integer methodCode = invocation.getMethodCode();
        // 当集合中找不到对应的，则方法并未被调用过，需要创建并绑定
        if (!methodMap.containsKey(methodCode)){
            final String key = ServiceNameBuilder.buildServiceKey(invocation.getClassName(),invocation.getServiceVersion());
            // 从本地缓存中获取类的实例化对象
            Object bean = Cache.SERVICE_MAP.get(key);
            // 获取类
            final Class<?> aClass = bean.getClass();
            // 根据方法名和参数类型获取方法
            final Method method = aClass.getMethod(invocation.getMethodName(),invocation.getParameterTypes());
            methodMap.put(methodCode,new MethodInvocation(bean,method));
        }
        final MethodInvocation methodInvocation = methodMap.get(methodCode);
        return methodInvocation.invoke(invocation.getParameter());
    }
}
